package com.sneakxy.mybatis.commons.repository.query;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.UpdateProvider;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.QueryMethod;

import com.sneakxy.mybatis.commons.orm.MybatisEntityManager;

/**
 * @author 潜行的青衣
 */
public class MybatisQueryMethod extends QueryMethod {
	
	private static final Set<Class<? extends Annotation>> sqlAnnotationTypes = new HashSet<Class<? extends Annotation>>();
	
	static {
		sqlAnnotationTypes.add(Select.class);
	    sqlAnnotationTypes.add(Insert.class);
	    sqlAnnotationTypes.add(Update.class);
	    sqlAnnotationTypes.add(Delete.class);
	    sqlAnnotationTypes.add(SelectProvider.class);
	    sqlAnnotationTypes.add(InsertProvider.class);
	    sqlAnnotationTypes.add(UpdateProvider.class);
	    sqlAnnotationTypes.add(DeleteProvider.class);
	}

	private Method method;
	
	private boolean mapperType;
	
	private MybatisEntityManager entityManager;
	/**
	 * @param method
	 * @param metadata
	 * @param factory
	 * @param entityManager
	 */
	public MybatisQueryMethod(
			Method method, 
			RepositoryMetadata metadata, 
			ProjectionFactory factory, 
			MybatisEntityManager entityManager) {
		super(method, metadata, factory);
		this.method = method;
		this.entityManager = entityManager;
		this.mapperType = this.hasAnnotationType(method, sqlAnnotationTypes);
	}

	public boolean hasStatement() {
		String statement = this.getEntityManager().getNamespacedId(method.getName());
		return this.getEntityManager().getConfiguration().hasStatement(statement);
	}
	
	private boolean hasAnnotationType(Method method, Set<Class<? extends Annotation>> types) {
		for (Class<? extends Annotation> type : types) {
			Annotation annotation = method.getAnnotation(type);
			if (annotation != null) {
				return true;
			}
		}
		return false;
	}

	public Method getQueryMethod() {
		return method;
	}

	public boolean isMapperType() {
		return mapperType;
	}

	public MybatisEntityManager getEntityManager() {
		return entityManager;
	}

}
